﻿
namespace Mulala.Cavan.Presentation.Seedwork
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics.Contracts;
    using System.Linq;
    using System.Web.Mvc;
    using Mulala.Cavan.Core.Extension;
    using Mulala.Cavan.Application.MainBoundedContext.SecurityModule;
    using Mulala.Cavan.Core.Message;
    using System.Threading;

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface | AttributeTargets.Method, AllowMultiple = true)]
    public class AccessFilterAttribute : ActionFilterAttribute, IAuthorizationFilter
    {
        #region IAuthorizationFilter Members
        public virtual void OnAuthorization(AuthorizationContext filterContext)
        {
            var controller = filterContext.Controller as IWebController<IWebModel>;
            var controllerName = filterContext.RouteData.Values["controller"].ToString();
            var actionName = filterContext.RouteData.Values["action"].ToString();
            object[] attrs = filterContext.ActionDescriptor.GetCustomAttributes(typeof(ActionUsedDeniedAttribute), true);
            bool actionUsedDenied = true;
            if (attrs != null && attrs.Length > 0)
            {
                actionUsedDenied = ((ActionUsedDeniedAttribute)attrs[0]).IsUsedDenied;
            }
            controller.Model.MasterModel.CurrentAction = actionName;
            var model = controller.Model.MasterModel.CurrentUserModel;
            
            if (controller.Is())
            {
                try
                {
                    var isAllowed = true;
                    if (controller.UseDenied)//控制器是否需要验证
                    {
                        if (!Thread.CurrentPrincipal.Identity.IsAuthenticated)
                        {
                            filterContext.Result = new HttpUnauthorizedResult();
                            isAllowed = false;
                        }
                        else
                        {
                            if (actionUsedDenied)
                            {
                                if (SecurityAppService.UserAccount.Roles.FirstOrDefault().IsUseDenied)//用户角色是否需要验证
                                {
                                    if (!SecurityAppService.GrantedControllers.Any(gc => gc.Name.ToLower() == controllerName.ToLower()))//用户角色是否拥有控制器权限
                                    {
                                        isAllowed = false;
                                    }
                                    else
                                    {
                                        //if (!SecurityAppService.GrantedControllers.FirstOrDefault(gc => gc.Name == controllerName).IsAllowedAllRoles)
                                        //{
                                        //    if (!SecurityAppService.GrantedActions.Any(ga => ga.Name == actionName))//用户角色是否拥有行为权限
                                        //    {
                                        //        isAllowed = false;
                                        //    }
                                        //}
                                        isAllowed = true;
                                    }
                                }
                            }
                        }
                    }

                    if (isAllowed)
                    {
                        return; // access is granted - other processing informs about reason for disallowing
                    }
                }
                catch (Exception ex)
                {
                    this.Log().Fatal("验证失败", ex);
                }
            }

            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                controller.Model.Messages.Clear();
                controller.Model.Messages.AddError(controller, "NoAccess", "没有权限 {0} {1} {2}", SecurityAppService.UserAccount.Name, controllerName, actionName);

                DenyAccess(filterContext);
            }
        }
        #endregion

        #region protected DenyAccess transfer
        protected virtual void DenyAccess(AuthorizationContext filterContext)
        {
            var controllerName = (string)filterContext.RouteData.Values["controller"];
            var action = (string)filterContext.RouteData.Values["action"];
            var controller = filterContext.Controller as IWebController<IWebModel>;

            var messages = controller.Is()
                               ? controller.Model.Messages
                               : new List<AppMessage>();
            // Model
            var model = new ExceptionModel();

            model.MasterModel.ControllerName = controllerName;
            model.MasterModel.CurrentAction = action;
            model.Messages = messages;

            // View result
            if (controller.Is())
            {
                var result = new ViewResult
                {
                    ViewData = new ViewDataDictionary<IExceptionModel>(model),
                    ViewName = @"~\Views\Error\NoAccess.cshtml"
                };
                filterContext.Result = result;
            }
            filterContext.HttpContext.Response.Clear();
            filterContext.HttpContext.Response.StatusCode = 403; // not authorized
        }
        #endregion protected DenyAccess transfer
    }
}